使用 ARIMA 等经典方法对时间序列进行建模时,方差或波动率随时间的变化可能会导致问题。
ARCH(自回归条件异方差方法)提供了一种方法来模拟时间序列中随时间变化的方差变化,以增加或减少波动性。这种方法的扩展为 GARCH(广义自回归条件异方差)允许该方法支持随时间变化的波动率的变化。
自回归模型可以为平稳 时间序列(AR)、具有趋势 (ARIMA) 和季节性成分 (SARIMA) 的单变量时间序列数据进行建模。
但这些模型无法对时间序列的方差改变情况进行建模。
处理方差改变的经典方法包括:使用变换来调整方差变化不大的时间序列,例如通过取Log 或使用 Box-Cox 变换。
在某些时间序列中,方差随时间不断变化。金融领域的时间序列称这种情形为波动性增加和减少。统计学称这为异方差。
如果方差的变化可以随时间相关,则可以使用自回归过程(例如 ARCH)对其进行建模。
自回归条件异方差或 ARCH 是一种显式模拟时间序列中随时间变化的方差变化的方法。
具体而言,ARCH 方法将时间步长的方差建模为来自平均过程(例如零均值)的残差函数。该模型必须指定滞后参数来定义要包含在模型中的先前残差的数量。 在ARCH(p)模型中,我们假定 $\sigma_t^2$ 的数据生成过程 (DGP) 是MA(p)模型,也就是说: $$ \sigma_t^2=\delta_0+\sum_{i=1}^p \delta_i u_{t-i}^2 $$
广义自回归条件异方差或 GARCH 是 ARCH 模型的扩展,它结合了移动平均分量和自回归分量。具体来说,该模型包括滞后方差项(例如,如果对另一个过程的白噪声残差建模时的观察结果),以及来自平均过程的滞后残差。
移动平均分量的引入允许模型对随时间变化的条件变化以及随时间变化的变化进行建模,包括有条件的方差增加和减少。
因此,该模型引入了一个新参数“p”,用于描述滞后方差项的数量:
GARCH 模型的一个普遍接受的符号是用p和q参数 GARCH(p, q) 指定 GARCH() 函数;例如 GARCH(1, 1) 将是一阶 GARCH 模型。
GARCH 模型包含 ARCH 模型,其中 GARCH(0, q) 等价于 ARCH(q) 模型。
GARCH模型形式。假设 $\left\{u_t\right\}$ 的 DGP是GARCH $(p, q)$ ,那么 $$ \begin{aligned} u_t & \sim N\left(0, \sigma_t^2\right) \\ \sigma_t^2 &=\delta_0+\sum_{i=1}^p \delta_i u_{t-i}^2+\sum_{j=1}^q \gamma_j \sigma_{t-j}^2 \end{aligned} $$
在本节中,我们将了解如何使用arch 库在 Python 中开发 ARCH 和 GARCH 模型。
首先,让我们准备一个可用于这些示例的数据集。
我们可以创建一个具有变化方差模型的数据集。 最简单的情况是一系列随机噪声,其中均值为零,方差从 0.0 开始并稳步增加。 我们可以在 Python 中使用gauss() 函数来实现这一点,该函数生成具有指定均值和标准差的高斯随机数。
# create dataset
data = [gauss(0, i*0.01) for i in range(1,100+1)]
# create a simple white noise with increasing variance
from random import gauss
from random import seed
from matplotlib import pyplot
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# plot
pyplot.plot(data)
pyplot.show()
# check correlations of squared observations
from random import gauss
from random import seed
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_acf
import numpy as np
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# square the dataset
squared_data = np.array([x**2 for x in data])
# create acf plot
plot_acf(squared_data)
构建 ARCH 模型涉及三个步骤:
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='ARCH', p=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
我们可以像使用 arch 库一样轻松地拟合 GARCH 模型。
arch_model ()函数可以指定 GARCH 而不是 ARCH 模型 vol='GARCH' 以及两者的滞后参数。
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='GARCH', p=15, q=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
参考资料
from random import gauss
from random import seed
from matplotlib import pyplot
# create dataset
data = [gauss(0, i*0.01) for i in range(1,100+1)]
# create a simple white noise with increasing variance
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# plot
pyplot.plot(data)
pyplot.show()
# check correlations of squared observations
from random import gauss
from random import seed
from matplotlib import pyplot
from statsmodels.graphics.tsaplots import plot_acf
import numpy as np
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# square the dataset
squared_data = np.array([x**2 for x in data])
# create acf plot
plot_acf(squared_data)
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='ARCH', p=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
Iteration: 1, Func. Count: 18, Neg. LLF: 88214.15274343832 Iteration: 2, Func. Count: 36, Neg. LLF: 145.16327370105464 Iteration: 3, Func. Count: 54, Neg. LLF: 128.0887135967567 Iteration: 4, Func. Count: 72, Neg. LLF: 109.21731760967693 Iteration: 5, Func. Count: 90, Neg. LLF: 36.505726167454 Iteration: 6, Func. Count: 108, Neg. LLF: 39.65736210558854 Iteration: 7, Func. Count: 126, Neg. LLF: 28.719728253674663 Iteration: 8, Func. Count: 143, Neg. LLF: 28.02026266328528 Iteration: 9, Func. Count: 161, Neg. LLF: 34.947196664051255 Iteration: 10, Func. Count: 180, Neg. LLF: 30.036303168280703 Iteration: 11, Func. Count: 198, Neg. LLF: 26.9167818648405 Iteration: 12, Func. Count: 216, Neg. LLF: 35.23299678777928 Iteration: 13, Func. Count: 235, Neg. LLF: 25.557794471124332 Iteration: 14, Func. Count: 253, Neg. LLF: 25.496876434441695 Iteration: 15, Func. Count: 271, Neg. LLF: 25.486204053803203 Iteration: 16, Func. Count: 289, Neg. LLF: 25.48610958123715 Iteration: 17, Func. Count: 307, Neg. LLF: 25.4821494694209 Iteration: 18, Func. Count: 324, Neg. LLF: 25.480673794020678 Iteration: 19, Func. Count: 341, Neg. LLF: 25.47836308055843 Iteration: 20, Func. Count: 358, Neg. LLF: 25.477639175671563 Iteration: 21, Func. Count: 375, Neg. LLF: 25.477510661344226 Iteration: 22, Func. Count: 392, Neg. LLF: 25.477507648462982 Iteration: 23, Func. Count: 408, Neg. LLF: 25.47750761478659 Optimization terminated successfully (Exit mode 0) Current function value: 25.477507648462982 Iterations: 23 Function evaluations: 408 Gradient evaluations: 23
D:\software_install\anaconda\lib\site-packages\arch\__future__\_utility.py:11: FutureWarning: The default for reindex is True. After September 2021 this will change to False. Set reindex to True or False to silence this message. Alternatively, you can use the import comment from arch.__future__ import reindexing to globally set reindex to True and silence this warning. warnings.warn(
# example of ARCH model
from random import gauss
from random import seed
from matplotlib import pyplot
from arch import arch_model
# seed pseudorandom number generator
seed(1)
# create dataset
data = [gauss(0, i*0.01) for i in range(0,100)]
# split into train/test
n_test = 10
train, test = data[:-n_test], data[-n_test:]
# define model
model = arch_model(train, mean='Zero', vol='GARCH', p=15, q=15)
# fit model
model_fit = model.fit()
# forecast the test set
yhat = model_fit.forecast(horizon=n_test)
# plot the actual variance
var = [i*0.01 for i in range(0,100)]
pyplot.plot(var[-n_test:])
# plot forecast variance
pyplot.plot(yhat.variance.values[-1, :])
pyplot.show()
Iteration: 1, Func. Count: 33, Neg. LLF: 134.2317665883839 Iteration: 2, Func. Count: 70, Neg. LLF: 95143.89889693505 Iteration: 3, Func. Count: 103, Neg. LLF: 544.0642933451215 Iteration: 4, Func. Count: 136, Neg. LLF: 359.71934329672257 Iteration: 5, Func. Count: 169, Neg. LLF: 120.68440702788735 Iteration: 6, Func. Count: 202, Neg. LLF: 57.67989249945465 Iteration: 7, Func. Count: 235, Neg. LLF: 37.233827705923716 Iteration: 8, Func. Count: 268, Neg. LLF: 44.28485299843633 Iteration: 9, Func. Count: 301, Neg. LLF: 30.955777300460745 Iteration: 10, Func. Count: 334, Neg. LLF: 26.957534677373722 Iteration: 11, Func. Count: 366, Neg. LLF: 31.3580409658397 Iteration: 12, Func. Count: 400, Neg. LLF: 30.014493583203443 Iteration: 13, Func. Count: 433, Neg. LLF: 28.461108093598074 Iteration: 14, Func. Count: 466, Neg. LLF: 27.699889811892838 Iteration: 15, Func. Count: 499, Neg. LLF: 26.904388797274514 Iteration: 16, Func. Count: 532, Neg. LLF: 25.516071922827045 Iteration: 17, Func. Count: 564, Neg. LLF: 25.510907831311023 Iteration: 18, Func. Count: 597, Neg. LLF: 25.783788607050088 Iteration: 19, Func. Count: 630, Neg. LLF: 25.49211347795663 Iteration: 20, Func. Count: 662, Neg. LLF: 25.485421075968024 Iteration: 21, Func. Count: 694, Neg. LLF: 25.47968365539404 Iteration: 22, Func. Count: 726, Neg. LLF: 25.47782215931985 Iteration: 23, Func. Count: 758, Neg. LLF: 25.4775259561624 Iteration: 24, Func. Count: 790, Neg. LLF: 25.477511388158838 Iteration: 25, Func. Count: 822, Neg. LLF: 25.477508049724243 Iteration: 26, Func. Count: 853, Neg. LLF: 25.477508012707627 Optimization terminated successfully (Exit mode 0) Current function value: 25.477508049724243 Iterations: 26 Function evaluations: 853 Gradient evaluations: 26
D:\software_install\anaconda\lib\site-packages\arch\__future__\_utility.py:11: FutureWarning: The default for reindex is True. After September 2021 this will change to False. Set reindex to True or False to silence this message. Alternatively, you can use the import comment from arch.__future__ import reindexing to globally set reindex to True and silence this warning. warnings.warn(